/**
  ******************************************************************************
  * @file
  * @brief
  * @author taoye
  * @version V1.0.0
  * @date 2021/01/01
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include "dev_tca9535.h"


/* Private defines -----------------------------------------------------------*/
#define INPUT0_PORT_REG         0x00
#define INPUT1_PORT_REG         0x01

#define OUTPUT0_PORT_REG        0x02
#define OUTPUT1_PORT_REG        0x03

#define POLARITY0_REG           0x04
#define POLARITY1_REG           0x05

#define CONFIG0_REG             0x06
#define CONFIG1_REG             0x07


/* Private Struct  -----------------------------------------------------------*/


/* Private enum    -----------------------------------------------------------*/


/* Private Variable  ---------------------------------------------------------*/
//Pointer

//Array

//Const

/* Private function prototypes -----------------------------------------------*/

/***********************************************************************************
 * @brief 
 * ex:
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
static int Tca9535_Check(dev_tca9535_t *this)
{
    int ret;

    ret = this->private.i2c.Check(&this->private.i2c, this->SLAVE_ADDR);
    if(ret < 0){
        return -1;
    }

    return 0;
}
/***********************************************************************************
 * @brief 
 * ex:
 * @par      设置端口输入输出
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
static void Tca9535_ModeSetBit(dev_tca9535_t *this, tca9535_mode_e mode, uint16_t bit)
{
    uint8_t data[2];

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Read(&this->private.i2c, this->SLAVE_ADDR, CONFIG0_REG, data, 2) < 0){
        ;
    }

    if(mode == TCA9535_INPUT){
        data[1] |= (uint8_t)((uint16_t)bit >> 8);
        data[0] |= (uint8_t)((uint16_t)bit >> 0);
    }
    else{
        data[1] &= (uint8_t)(~(uint16_t)bit >> 8);
        data[0] &= (uint8_t)(~(uint16_t)bit >> 0);        
    }

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Write(&this->private.i2c, this->SLAVE_ADDR, CONFIG0_REG, data, 2) < 0){
        ;
    }
}
/***********************************************************************************
 * @brief    功能说明：驱动TCA9535输出管脚电平
 * ex:
 * @par       val:写1为设置高电平，写0为设置低电平
 *           输入参数：dev_tca9535_t *this - TCA9535控制模块 
 *                     uint8_t val - 设置高低电平标识：1-输出高电平，0-输出低电平
*                     uint16_t bit - 待驱动TCA9535的管脚，为1的bit位为待控制管脚
 *           输出参数：无
 * None
 * @par 
 * None
 * @retval   返回值：无
 **********************************************************************************/
static void Tca9535_WriteBit(dev_tca9535_t *this, uint8_t val, uint16_t bit)
{
    uint8_t data[2];
    uint8_t temp;

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Read(&this->private.i2c, this->SLAVE_ADDR, OUTPUT0_PORT_REG, data, 2) < 0){
        ;
    }
    
    data[0] = 0;
    data[1] = 0;

    if(val){
        data[1] |= (uint8_t)((uint16_t)bit >> 8);
        data[0] |= (uint8_t)((uint16_t)bit >> 0);
    }
    else{
        temp = (uint8_t)(~(uint16_t)bit >> 8);
        data[1] |= temp;
        temp = (uint8_t)(~(uint16_t)bit >> 0);
        data[0] |= temp;        
    }

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Write(&this->private.i2c, this->SLAVE_ADDR, OUTPUT0_PORT_REG, data, 2) < 0){
        ;
    }
//    uint8_t data[2];

//    // 错误时重运行，中断或线程打断操作时可以进行重发
//    while(this->private.i2c.Read(&this->private.i2c, this->SLAVE_ADDR, OUTPUT0_PORT_REG, data, 2) < 0){
//        ;
//    }

//    if(val){
//        data[1] |= (uint8_t)((uint16_t)bit >> 8);
//        data[0] |= (uint8_t)((uint16_t)bit >> 0);
//    }
//    else{
//        data[1] &= (uint8_t)(~(uint16_t)bit >> 8);
//        data[0] &= (uint8_t)(~(uint16_t)bit >> 0);        
//    }

//    // 错误时重运行，中断或线程打断操作时可以进行重发
//    while(this->private.i2c.Write(&this->private.i2c, this->SLAVE_ADDR, OUTPUT0_PORT_REG, data, 2) < 0){
//        ;
//    }
}
/***********************************************************************************
 * @brief        读取输入引脚的值
 * ex:
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
static uint8_t Tca9535_ReadBit(dev_tca9535_t *this, uint16_t bit)
{
    uint8_t data[2];

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Read(&this->private.i2c, this->SLAVE_ADDR, INPUT0_PORT_REG, data, 2) < 0){

    }

    data[1] &= (uint8_t)((uint16_t)bit >> 8);
    data[0] &= (uint8_t)((uint16_t)bit >> 0);

    if(data[0] != 0 || data[1] != 0){
        return 1;
    }

    return 0;
}

/***********************************************************************************
 * @brief        读取输入引脚的值
 * ex:
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
static uint16_t Tca9535_ReadData(dev_tca9535_t *this)
{
    uint8_t temp_data[2];

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Read(&this->private.i2c, this->SLAVE_ADDR, INPUT0_PORT_REG, temp_data, 2) < 0)
    {

    }
    return (temp_data[1]<<8|temp_data[0]);
}
/***********************************************************************************
 * @brief 
 * ex:
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
int Dev_Tca9535_Init(dev_tca9535_t *this)
{
    this->private.gpio_int.MODE      = INPUT_UP;
    this->private.gpio_int.PIN       = this->PIN_INT;

//    if(Drv_Gpio_Init(&this->private.gpio_int) < 0){
//        return -1;
//    }

    this->private.i2c.PIN_SDA        = this->PIN_SDA;
    this->private.i2c.PIN_SCL        = this->PIN_SCL;
    this->private.i2c.SPEED          = I2C_SPEED_MEDIUM;
    this->private.i2c.WIDTH          = I2C_WIDTH_BYTE;
    this->private.i2c.ACK_TIMEOUT    = I2C_TIMEOUT_STOP;
    this->private.i2c.ACK_WAIT_US    = 100;
    this->private.i2c.SAMPLE_DELAY = this->SAMPLE_DELAY;
	
    if(Drv_I2c_Init(&this->private.i2c) < 0){
        return -1;
    }

    this->Check         = Tca9535_Check;
    this->WriteBit      = Tca9535_WriteBit;
    this->ModeSetBit    = Tca9535_ModeSetBit;
    this->ReadData      = Tca9535_ReadData;

	return 0;
}








